#region File Description
//-----------------------------------------------------------------------------
// GameplayScreen.cs
//
// Microsoft XNA Community Game Platform
// Copyright (C) Microsoft Corporation. All rights reserved.
//-----------------------------------------------------------------------------
#endregion

#region Using Statements
using System;
using System.Threading;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Drawing;
#endregion

namespace MyXnaGame
{
    /// <summary>
    /// This screen implements the actual game logic. It is just a
    /// placeholder to get the idea across: you'll probably want to
    /// put some more interesting gameplay in here!
    /// </summary>
    class GameplayScreen : GameScreen
    {
        #region Fields
        PlayerSprite mySprite;
        //
        HudContainer hudContainer = new HudContainer();
        Texture2D clockTexture;

        SafeArea safeArea;
        Vector2 safeTopLeft = Vector2.Zero; // (2.0f * (safeArea.dx), 1.5f * (safeArea.dy));
        ContentManager content;
        SpriteFont gameFont;
        SpriteFont hudFont;

        Vector2 enemyPosition = new Vector2(100, 100);

        Random random = new Random();

        float pauseAlpha;

        #endregion

        #region Initialization


        /// <summary>
        /// Constructor.
        /// </summary>
        public GameplayScreen()
        {
            //
            safeArea = new SafeArea();
            mySprite = new PlayerSprite();
            TransitionOnTime = TimeSpan.FromSeconds(1.5);
            TransitionOffTime = TimeSpan.FromSeconds(0.5);
        }


        /// <summary>
        /// Load graphics content for the game.
        /// </summary>
        public override void LoadContent()
        {
            if (content == null)
                content = new ContentManager(ScreenManager.Game.Services, "Content");

            DrawingHelper.Initialize(ScreenManager.GraphicsDevice);
            //
            gameFont = content.Load<SpriteFont>("gamefont");
            hudFont = content.Load<SpriteFont>("menufont");
            //
            safeArea.LoadGraphicsContent(ScreenManager.GraphicsDevice);
            //
            hudContainer.LoadGraphicsContent(ScreenManager.GraphicsDevice, hudFont, safeArea);
            var hudScore = new HudTextComponent("SCORE: 100", HudComponent.PresetPosition.TopLeft);
            var hudHealth = new HudTextComponent("HEALTH: 300", HudComponent.PresetPosition.TopRight);
            var hudLives = new HudTextComponent("LIVES: 3", HudComponent.PresetPosition.MiddleLeft);
            var hudAmmo = new HudTextComponent("Ammo: 447", HudComponent.PresetPosition.MiddleRight);
            var hudName = new HudTextComponent("Angry Zombie...", HudComponent.PresetPosition.BottomLeft);
            var hudInfo = new HudTextComponent("...Ninja Cats!", HudComponent.PresetPosition.BottomRight);
            //
            hudContainer.Add(hudScore);
            hudContainer.Add(hudHealth);
            hudContainer.Add(hudLives);
            hudContainer.Add(hudAmmo); ;
            hudContainer.Add(hudName);
            hudContainer.Add(hudInfo);
            //
            clockTexture = content.Load<Texture2D>("HudGraphics/clock");
            var hudClock = new HudGraphicComponent(clockTexture, HudComponent.PresetPosition.TopCenter);
            hudContainer.Add(hudClock);
            //
            mySprite.LoadContent(content, "Player");

            // A real game would probably have more content than this sample, so
            // it would take longer to load. We simulate that by delaying for a
            // while, giving you a chance to admire the beautiful loading screen.
            Thread.Sleep(1000);

            // once the load has finished, we use ResetElapsedTime to tell the game's
            // timing mechanism that we have just finished a very long frame, and that
            // it should not try to catch up.
            ScreenManager.Game.ResetElapsedTime();
        }


        /// <summary>
        /// Unload graphics content used by the game.
        /// </summary>
        public override void UnloadContent()
        {
            content.Unload();
        }


        #endregion

        #region Update and Draw


        /// <summary>
        /// Updates the state of the game. This method checks the GameScreen.IsActive
        /// property, so the game will stop updating when the pause menu is active,
        /// or if you tab away to a different application.
        /// </summary>
        public override void Update(GameTime gameTime, bool otherScreenHasFocus,
                                                       bool coveredByOtherScreen)
        {
            base.Update(gameTime, otherScreenHasFocus, false);

            // Gradually fade in or out depending on whether we are covered by the pause screen.
            if (coveredByOtherScreen)
                pauseAlpha = Math.Min(pauseAlpha + 1f / 32, 1);
            else
                pauseAlpha = Math.Max(pauseAlpha - 1f / 32, 0);

            if (IsActive)
            {
                // Apply some random jitter to make the enemy move around.
                const float randomization = 10;

                enemyPosition.X += (float)(random.NextDouble() - 0.5) * randomization;
                enemyPosition.Y += (float)(random.NextDouble() - 0.5) * randomization;
                var enemyText = "XNA Basic Starter Kit!";
                var enemyDimensions = gameFont.MeasureString(enemyText);
                var enemyRectangle = new Rectangle(
                    (int)enemyPosition.X, (int)enemyPosition.Y, 
                    (int)enemyDimensions.X, (int)enemyDimensions.Y);

                // Apply a stabilizing force to stop the enemy moving off the screen.
                Vector2 targetPosition = new Vector2(
                    ScreenManager.GraphicsDevice.Viewport.Width / 2 - enemyDimensions.X / 2,
                    200);

                enemyPosition = Vector2.Lerp(enemyPosition, targetPosition, 0.05f);
                mySprite.IsColliding = mySprite.GetCollisionRect().Intersects(enemyRectangle);
                mySprite.Update(gameTime);

            }
        }


        /// <summary>
        /// Lets the game respond to player input. Unlike the Update method,
        /// this will only be called when the gameplay screen is active.
        /// </summary>
        public override void HandleInput(InputState input) //, GameTime gameTime)
        {
            if (input == null)
                throw new ArgumentNullException("input");

            // Look up inputs for the active player profile.
            int playerIndex = (int)ControllingPlayer.Value;

            KeyboardState keyboardState = input.CurrentKeyboardStates[playerIndex];
            GamePadState gamePadState = input.CurrentGamePadStates[playerIndex];

            // The game pauses either if the user presses the pause button, or if
            // they unplug the active gamepad. This requires us to keep track of
            // whether a gamepad was ever plugged in, because we don't want to pause
            // on PC if they are playing with a keyboard and have no gamepad at all!
            bool gamePadDisconnected = !gamePadState.IsConnected &&
                                       input.GamePadWasConnected[playerIndex];

            if (input.IsPauseGame(ControllingPlayer) || gamePadDisconnected)
            {
                ScreenManager.AddScreen(new PauseMenuScreen(), ControllingPlayer);
            }
            else
            {
                mySprite.HandleInput(keyboardState, gamePadState, input, safeArea);
            }
        }



        /// <summary>
        /// Draws the gameplay screen.
        /// </summary>
        public override void Draw(GameTime gameTime)
        {
            // This game has a blue background. Why? Because!
            ScreenManager.GraphicsDevice.Clear(ClearOptions.Target,
                                               Color.CornflowerBlue, 0, 0);

            // Our player and enemy are both actually just text strings.
            SpriteBatch spriteBatch = ScreenManager.SpriteBatch;

            spriteBatch.Begin();

            // draw hud
            hudContainer.Draw(spriteBatch);

            spriteBatch.DrawString(gameFont, "XNA Basic Starter Kit!",
                                   enemyPosition, Color.DarkRed);

#if DEBUG
            safeArea.Draw(spriteBatch);
#endif

            // debug info
            var safeAreaInfo = "dx=" + safeArea.dx + ",dy=" + safeArea.dy
                + ",w=" + safeArea.width + ",h=" + safeArea.height;
                //+ ", H = " + playerHorizDirection
                //+ ", V = " + playerVertDirection;
            spriteBatch.DrawString(gameFont, safeAreaInfo, safeTopLeft, Color.Green);

            //
            mySprite.Draw(spriteBatch);
            //
            DrawingHelper.DrawCircle(new Vector2(500, 200), 50, Color.Yellow, true);
            DrawingHelper.DrawRectangle(100, 350, 150, 375, Color.MidnightBlue, true);
            DrawingHelper.DrawRectangle(new Vector2(300, 300), new Vector2(100, 50), Color.Gold, false);
            //
            spriteBatch.End();

            // If the game is transitioning on or off, fade it out to black.
            if (TransitionPosition > 0 || pauseAlpha > 0)
            {
                float alpha = MathHelper.Lerp(1f - TransitionAlpha, 1f, pauseAlpha / 2);

                ScreenManager.FadeBackBufferToBlack(alpha);
            }
        }


        #endregion
    }
}
